﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace FilesMerge
{ 
    public delegate void MergeProcessChanged(int count,float percantage);
    public class Files
    {
        sealed class Instance
        {
            static Instance()
            { }
            internal static Files files = new Files();
        }

        public static Files Singleton
        {
            get { return Instance.files; }
        }

        public MergeProcessChanged ProcessMergeChangedHandler { get; set; }

        public Files()
        { }

        /// <summary>
        /// 获取文件夹下的所有文件
        /// </summary>
        /// <param name="folder"></param>
        /// <param name="searchParttens"></param>
        /// <param name="allFiles"></param>
        public void GetFolderFiles(string folder, string[] searchParttens, ref List<string> allFiles)
        {
            string[] files = null;

            for (int i = 0; i < searchParttens.Length; ++i)
            {
                files = Directory.GetFiles(folder, searchParttens[i]);
                if (files.Length > 0)
                {
                    allFiles.AddRange(files);
                }
            }
            string[] dirs = Directory.GetDirectories(folder);
            for (int i = 0; i < dirs.Length; ++i)
            {
                GetFolderFiles(dirs[i], searchParttens, ref allFiles);
            }
        }

        /// <summary>
        /// 将多个文件合并到一个文件
        /// </summary>
        /// <param name="srcFiles">原文件集合</param>
        /// <param name="dstFile">合并后的文件</param>
        ///  <param name="isWriteFileName">是否写入文件名</param>
        /// <returns></returns>
        public bool WriteMergeFiles(List<string> srcFiles, string dstFile, bool isWriteFileName = false)
        {
            try
            {
                srcFiles.Sort();

                using (FileStream fwrite = new FileStream(dstFile, FileMode.Create, FileAccess.ReadWrite))
                {
                    byte[] buffer = new byte[8192];
                    byte[] newline = Encoding.UTF8.GetBytes(Environment.NewLine);
                    int len = 0;
                    double total = (double)srcFiles.Count;

                    for (int i = 0; i < srcFiles.Count; ++i)
                    {
                        if (isWriteFileName)
                        {
                            StringBuilder sb = new StringBuilder();
                            sb.AppendLine("--------------" + Path.GetFileName(srcFiles[i]) + "--------------");
                            byte[] fname = Encoding.UTF8.GetBytes(sb.ToString());
                            fwrite.Write(fname, 0, fname.Length);
                           
                        }

                        using (FileStream fread = new FileStream(srcFiles[i], FileMode.Open, FileAccess.Read))
                        {
                            do
                            {
                                len = fread.Read(buffer, 0, buffer.Length);
                                fwrite.Write(buffer, 0, len);
                            } while (len > 0);
                        }
                        fwrite.Write(newline, 0, newline.Length);

                        if (ProcessMergeChangedHandler != null)
                        {
                            ProcessMergeChangedHandler(i + 1, (float)Math.Round((i+1) / total, 2) * 100);
                        }
                    }
                    fwrite.Flush();
                }
                return true;
            }
            catch
            {
                return false;
            }
        }

        public bool IsExistFolder(string folder)
        {
           return Directory.Exists(folder);
        }

        public bool IsExistFile(string file)
        {
            return File.Exists(file);
        }
    }
}
